/**
 * 
 */
package org.hotpotmaterial.codegenn2.config.security.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hotpotmaterial.codegenn2.common.HmCodeGenConstants;
import org.hotpotmaterial.codegenn2.config.security.service.IAccountTokenService;
import org.hotpotmaterial.codegenn2.dto.LoginDTO;
import org.hotpotmaterial.codegenn2.entity.HmteamAccount;
import org.hotpotmaterial.codegenn2.exception.TempDisableException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * @author cakydeveloper
 *
 */
@Slf4j
public class AuthenticationTokenFilter extends BasicAuthenticationFilter {

	private IAccountTokenService tokenService;

	public AuthenticationTokenFilter(AuthenticationManager authenticationManager) {
		super(authenticationManager);
	}

	public AuthenticationTokenFilter(AuthenticationManager authenticationManager, IAccountTokenService tokenService) {
		super(authenticationManager);
		this.tokenService = tokenService;
	}

	/**
	 * 拦截所有请求
	 */
	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
		SecurityContextHolder.getContext().setAuthentication(authentication);
		HmteamAccount user = null;
		if (null != authentication) {
			user = (HmteamAccount) authentication.getPrincipal();
		}
		// 判断路径是否拦截
		boolean shouldNotBeChecked = "/hmteam/codegen/v1/accounts/login_user/upt_pwd".equals(request.getRequestURI());
		if (!shouldNotBeChecked && null != user && user.getIsDeleted() == HmCodeGenConstants.DATA_IS_TEMP_VALID) {
			// 用户暂时不可用
			this.onUnsuccessfulAuthentication(request, response,
					new TempDisableException(user.getAuthToken(), "User is not valid temporarily"));
		} else if (request.getRequestURI().startsWith("/hmteam/codegen/admin")) {
			// 判断是否有admin权限
			if (HmCodeGenConstants.USER_IS_ADMIN != user.getRoleType()) {
				throw new InsufficientAuthenticationException("User is not admin");
			}
		} else {
			chain.doFilter(request, response);
		}
	}

	/**
	 * 获取用户信息
	 * 
	 * @param request
	 * @return
	 */
	private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
		String token = request.getHeader("AUTH_TOKEN");
		if (token != null && tokenService != null) {
			HmteamAccount user = tokenService.getUser(token);
			return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
		}
		return null;
	}

	/**
	 * 用户信息获取失败
	 */
	@Override
	protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException failed) throws IOException {

		SecurityContextHolder.clearContext();

		// 设置ContentType
		response.setContentType("application/json;charset=UTF-8");
		// 初始化RESPONSE消息体的对象
		LoginDTO result = new LoginDTO();
		if (failed instanceof TempDisableException) {
			TempDisableException tempFailed = (TempDisableException) failed;
			// 设置HTTP协议CODE
			response.setStatus(HttpServletResponse.SC_FORBIDDEN);
			result.setSuccess(true);
			// 返回状态403
			result.setStatus(HttpServletResponse.SC_FORBIDDEN);
			// 设置错误消息
			result.setErrorMessage(failed.getMessage());
			result.setData(tempFailed.getToken());
		} else {
			// 设置HTTP协议CODE
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			result.setSuccess(true);
			// 返回状态403
			result.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			// 设置错误消息
			result.setErrorMessage(failed.getMessage());
		}
		// 写入RESPONSE
		PrintWriter out = null;
		// 转JSON
		ObjectMapper mapper = new ObjectMapper();
		// 将RESULT对象转为JSON字符串
		String resultJson = mapper.writeValueAsString(result);
		try {
			// 写入RESPONSE
			out = response.getWriter();
			out.append(resultJson);
		} catch (IOException e) {
			log.error("Token authenticate failed!!!", e);
		} finally {
			if (out != null) {
				// 关闭WRITER
				out.close();
			}
		}

	}

}
